﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Drawing; //For Color(s) class
using System.Diagnostics; 
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
//using Microsoft.DirectX.DirectPlay;
//using Microsoft.DirectX.DirectSound;
//using Microsoft.DirectX.AudioVideoPlayback;
using DirectX_CS;

//www reference: 	http://www.c-sharpcorner.com/Blogs/BlogDetail.aspx?BlogId=71

namespace DirectX_CS
{

public class MainProgram
{
	private static bool exitProgram = false;

	private static MainProgram onlyProgram = null;
	public static MainProgram OnlyProgram
	{
		get { return onlyProgram; }
		set { onlyProgram = value; }
	}

	private static Device mDxDevice = null;
	public static Device DxDevice
	{
		get { return mDxDevice; }
		set { mDxDevice = value; }
	}


	private DirectXForm mFrm = null; //was just a Form, now its a Form that returns a handle to renderable device.
	public DirectXForm WindowsForm
	{
		get { return mFrm; }
		set { mFrm = value; }
	}

	private Material mMaterial; //see InitializeForm, not nullable
	[PGBrowsable]
	public Material Material
	{
		get { return mMaterial; }
		set { mMaterial = value; }
	}
	//protected bool bDoMotion = false;

	private int mAlphaBlendingType = 1;
	private bool mLighting = true;

	private PrimitiveManager mRendererManager = null; //i had forgot to initialize this but the code  was still running ??? i think.   \
	[PGBrowsable]
	public PrimitiveManager RendererManager
	{
		get { return mRendererManager; }
		set { mRendererManager = value; }
	}
	public Lighting LightingForm
	{
		get { return mLightingForm; }
	}
	public Camera DefaultCameraForm
	{
		get { return mCameraForm; }
	}
	public OutputForm OutputForm
	{
		get { return mOutputForm; }
	}
 	public ObjectsEditor PrimitivesEditorForm
	{
		get { return mPrimitivesEditor; }
	}

	~MainProgram()
	{
		mRendererManager = null;
		mLightingForm = null;
		mCameraForm = null;
		mOutputForm = null;
		mPrimitivesEditor = null;
	}

	public static bool ExitProgram
	{
		get { return exitProgram; }
		set 
		{ 
			exitProgram = value; 
		}
	}
	
	MainProgram() //Empty constructor
	{ Initialize(null); }

	//Constructor of the three required pieces in order for the system to work.
	MainProgram(Form display)
	{
		Initialize(display); //see Initialize...
	}

	/// <summary>
	/// Called during construction primarily to make sure that
	/// the paramaters are not null. If Form is null then the 
	/// we create the default form. If the Device is null then
	/// we create a working graphics device.
	/// Also wires up the form to the program shutdown mechanism.
	/// 
	/// //NOTE: create your Device and display first
	/// </summary>
	/// <param name="dev">if null is used for a device or form then the device or form will be created!</param>
	/// <param name="display">if null is used for a device or form then the device or form will be created!</param>
	void Initialize(Form displayForm)
	{
		onlyProgram = this;

		//CreateDevice requires the form be created first!, 
		if (displayForm == null)
		{
			mFrm = new DirectXForm();
		}
		if (mDxDevice == null)
        {
            mDxDevice = CreateDevice(); //CreateDevice requires the form be created before the 'Device'!, 
        }
		mFrm.Show();

		mDxDevice.Transform.World = Matrix.Identity;

		SetupTransformProjection();
		InitializeOrResetLights();
        ResetDefaultMaterial();
		InitializeRenderState();

        //INITIALIZE FORMS
		mRendererManager = new PrimitiveManager();
		mFrm.RendererManager = mRendererManager;

		//initialize forms before primitives
		InitializeForms();

		InitializePrimitivesMain();

		SetViewport(); //called in renderscene

		mCameraForm.SetViewTransform();
	}

	private SelectMesh meshTest = null;
	private Lighting mLightingForm = null;
	private Camera mCameraForm = null;
	private OutputForm mOutputForm = null;
	private ObjectsEditor mPrimitivesEditor = null;


	/// <summary>
	/// BEGIN: WHERE OBJECTS ARE CREATED IN THE INITIAL SCENE
	/// </summary>
	void InitializePrimitivesMain()
	{

		mRendererManager.SuppressRecreateBuffer = true;


		////begin: create a cool looking platform and axis...
		//Cartesian3dAxis mCartesianAxis = new Cartesian3dAxis(-1000f, 1000f, -1000f, 1000f, -1000f, 1000f, 20, 20, 20);
		//ObjectsEditor.OnlyForm.AddUserObject(mCartesianAxis);
		//Cartesian3dAxis mCartesianAxisSmaller = new Cartesian3dAxis( -100f, 100f, -100, 100f, -100f, 100f, 20, 20, 20);
		//ObjectsEditor.OnlyForm.AddUserObject(mCartesianAxisSmaller);
		Cartesian3dAxis mCartesianAxisMuchSmaller = new Cartesian3dAxis( -10f, 10f, -10f, 10f, -10f, 10f, 20, 20, 20);
		ObjectsEditor.OnlyForm.AddUserObject(mCartesianAxisMuchSmaller);
		
		


		float size = 10000;
		int divs = 40;
		WaveEditor mFluid = new WaveEditor(mDxDevice, mRendererManager, mFrm, -size, size, divs, -size, size, divs, 0f, 1f, true);
		//mFluid.EnableCallRenderIndexedPrimitives = true; mFluid.EnableCallRenderPrimitives = true;
		ObjectsEditor.OnlyForm.AddUserObject(mFluid);

		//Simple3dRectangle ocean = new Simple3dRectangle(Simple3dRectangle.DefaultPlaneZFunc, -10000, 10000, -10000, 10000);
		//ocean.MainVertexColor = mFluid.MainVertexColor;
		//ObjectsEditor.OnlyForm.AddUserObject(ocean);

		//FontMesh ftemp = new FontMesh(true);
		//ObjectsEditor.OnlyForm.AddUserObject(ftemp);

		/*
		mSurfaceLines = new Cartesian3dFunction(mDxDevice, mRendererManager, CartesianDataCreator.cosf, CartesianDataCreator.sinf, CartesianDataCreator.linetf, -1000, 1000, 2000);
		mSurfaceLines.Position = new Vector3(-10, 0, 10);
        CartesianDataCreator dc = new CartesianDataCreator(CartesianDataCreator.xyZFuncSinCos, -20, 20, -20, 20, 50, 50);
		mSurfaceLines2 = new Cartesian3dFunction(mDxDevice, mRendererManager, CartesianDataCreator.cosf, -1000, 1000, 2000);
        mSurfaceLines3 = new Cartesian3dFunction(mDxDevice, mRendererManager, CartesianDataCreator.xyZFuncPlaneXY, -10, 10, -10, 10, 25, 25);
        mSurfaceLines3.Position = new Vector3 (-40,-40,10);
		mSurface = new Cartesian3dSurface(mDxDevice, mRendererManager, dc); //mSurfaceLines
		mSurface.Position = new Vector3(15, 15, 10);
		 * 
		mCartesianPlane = new Simple3dRectangle(mDxDevice, mRendererManager, Simple3dRectangle.DefaultPlaneZFunc, 0, 111f, 0, 111f);
		mCartesianPlane.Position = new Vector3(-30, -30, 10);

		TriangleFan m3dCircle = new TriangleFan(10);
		m3dCircle.Position = new Vector3(-30, -30, 10);

		Simple3dCircle mAxisCircle = new Simple3dCircle((float)20f, 0, Color.Blue);
		mAxisCircle.Position = new Vector3(-10, -10, 10);
		mAxisCircle2 = new Cartesian3dCircle(mDxDevice, mRendererManager, (float)5f, 0);		
	*/

		meshTest = new SelectMesh(mFluid, true );

		///Now that all the initializations have taken place (constructors, registration in particular), ...
		/// turn off suppression so data can be gathered and the Vertex Buffer created.
																					  
		mRendererManager.SuppressRecreateBuffer = false; 
	

		/// SET THE ALMIGHTY CAMERA POSITION. IT LOOKS AT THE ORIGIN AT (0,0,0)	 IN 3-d coordinates... 
		Camera.DefaultCamera.SetCamera(new Vector3(0, 0, 0), new Vector3(-54.1f, -236.1f, 42.7f));
		Camera.DefaultCamera.SetViewTransform();
		/// End Set Camera Position and Look at Point
		/// 


		//now we are done aadding all the objects time to refresh the list
		ObjectsEditor.ReloadList();
	}  	
	/// <summary>
	/// END OF: OBJECTS CREATED IN THE INITIAL SCENE
	/// </summary>
	/// 
	void InitializeForms()
	{
		mPrimitivesEditor = new ObjectsEditor(mDxDevice, mRendererManager, this); //put before camera form and object creation

		mCameraForm = Camera.DefaultCamera;
		mCameraForm.Text = "Default Camera Form";

		//mCameraForm.Show();
		mOutputForm = new OutputForm(mFrm);
		mLightingForm = new Lighting(mDxDevice, mRendererManager, mFrm);

	}

		/// <summary>
		/// CreateDevice 
		/// </summary>
		/// <returns></returns>
		Device CreateDevice()
		{
			Device dx = null;

			PresentParameters pps = new PresentParameters();

            CreateFlags flags;
            Caps caps = Manager.GetDeviceCaps(Manager.Adapters.Default.Adapter, DeviceType.Hardware);
			if (caps.DeviceCaps.SupportsHardwareTransformAndLight)
			{
				flags = CreateFlags.HardwareVertexProcessing;
			}
			else
			{
				flags = CreateFlags.SoftwareVertexProcessing;
			}
			/*
			pps.BackBufferCount = 1;
			pps.BackBufferWidth = mFrm.ClientSize.Width;
			pps.BackBufferHeight = mFrm.ClientSize.Height;
			pps.BackBufferFormat = Format.Unknown;
			pps.MultiSample = MultiSampleType.EightSamples;
			*/

			pps.Windowed = true; //important for control surfaces
			pps.SwapEffect = SwapEffect.Discard;
			pps.DeviceWindow = (Control)mFrm; //instead of a form use a control or vice versa

			/*
			pps.AutoDepthStencilFormat = DepthFormat.D16;
			pps.PresentationInterval = PresentInterval.Immediate;
			pps.PresentFlag = PresentFlag.DiscardDepthStencil;
			pps.BackBufferFormat = Format.Unknown;
			pps.EnableAutoDepthStencil = true;            
			*/

            PresentParameters[] ppa = new PresentParameters[1] { pps };
            IntPtr RenderWindowHandle = mFrm.Handle;
            int adapter = 0;

			dx = new Device(adapter,
				DeviceType.Hardware, //DeviceType.Hardware //DeviceType.Reference, 
				RenderWindowHandle, //handle to a control or window.
				flags,//CreateFlags.MultiThreaded | CreateFlags.MixedVertexProcessing, 
				ppa); // Put everything into the device

			dx.DeviceLost += new EventHandler(mDxDevice_DeviceLost);
            dx.DeviceReset += new EventHandler(dx_DeviceReset);

			return dx;
		}

        void dx_DeviceReset(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }

		void mDxDevice_DeviceLost(object sender, EventArgs e)
		{
			exitProgram = true;
		}

		protected void PrepareForTransparency()
		{
			mDxDevice.RenderState.AlphaBlendEnable = true;
			mDxDevice.RenderState.SourceBlend = Blend.SourceAlpha;
			mDxDevice.RenderState.DestinationBlend = Blend.InvSourceAlpha;
			//specify that alpha is taken from the vertex color: ref: http://www.two-kings.de/tutorials/dxgraphics/dxgraphics07.html
			//mDxDevice.SetTextureStageState(0, TextureStageStates.AlphaArgument, true);
			mDxDevice.RenderState.ZBufferEnable = false;
		}
		protected void InitializeRenderState()
		{
			AlphaBlendingType = mAlphaBlendingType; //private method sets the render state

			mDxDevice.RenderState.FillMode = FillMode.Solid;// FillMode.WireFrame; // FillMode.Point, // FillMode.Solid
			mDxDevice.RenderState.CullMode = Cull.None;
			mDxDevice.RenderState.AlphaBlendEnable = true;

			mDxDevice.RenderState.ZBufferEnable = false; 
            //mDxDevice.RenderState.ZBufferFunction = Compare.Greater;
			//mDxDevice.RenderState.ZBufferWriteEnable = true;

			
			mDxDevice.RenderState.DepthBias = 0f; 
			mDxDevice.RenderState.PointSize = 1f;

			mDxDevice.RenderState.ColorVertex = true; //Enabling per-vertex color allows the system to include the color defined for individual verts in its lighting calculations. (http://msdn.microsoft.com/en-us/library/microsoft.windowsmobile.directx.direct3d.renderstatemanager.colorvertex.aspx)

			mDxDevice.RenderState.VertexBlend = VertexBlend.ThreeWeights;   //was VertexBlend.ThreeWeights;

			//mDxDevice.RenderState.DitherEnable = false;
			
			//mDxDevice.RenderState.AdaptiveTessellateX = 0.0f;
			//mDxDevice.RenderState.AdaptiveTessellateY = 0.0f;
			//mDxDevice.RenderState.AdaptiveTessellateZ = 0.0f;

			mDxDevice.RenderState.FogColor = Color.White;
			//mDxDevice.RenderState.FogDensity  =   //for exponential fog modes
			mDxDevice.RenderState.FogEnd = 10000f;
			mDxDevice.RenderState.FogStart = 1000f;
			mDxDevice.RenderState.FogTableMode  = FogMode.Linear;
			mDxDevice.RenderState.FogVertexMode = FogMode.Linear;
			
			mDxDevice.RenderState.FogEnable = false;

			//int[] functionTokenBlendOperations = new int[{....
			//mDxDevice.VertexShader = new VertexShader(mDxDevice, 


			mDxDevice.RenderState.SpecularEnable = true;
			mDxDevice.RenderState.SpecularMaterialSource = ColorSource.Material;
				mDxDevice.RenderState.DiffuseMaterialSource = ColorSource.Material;
			mDxDevice.RenderState.AmbientMaterialSource = ColorSource.Color1; //color1

            mDxDevice.RenderState.UseWBuffer = false;
			mDxDevice.RenderState.AntiAliasedLineEnable = false;										 
			mDxDevice.RenderState.BlendOperation = BlendOperation.Add;
            mDxDevice.RenderState.NormalizeNormals = false;
			mDxDevice.RenderState.ShadeMode = ShadeMode.Phong;
			mDxDevice.RenderState.Lighting = true;
			mDxDevice.RenderState.IndexedVertexBlendEnable = true;

			mDxDevice.RenderState.Ambient = Color.Black;

			PrepareForTransparency();
		}
		[PGBrowsable]
		public Color AmbientColor
		{
			get { return mDxDevice.RenderState.Ambient; }
			set { mDxDevice.RenderState.Ambient = value; }
		}
		[PGBrowsable]
		public int AlphaBlendingType
		{
			get { return mAlphaBlendingType; }
			set 
			{ 
				mAlphaBlendingType = value;
				if (value == 0)
				{
					//alpha blending looks good with transparency too.			
					mDxDevice.RenderState.DestinationBlend = Blend.DestinationColor;
					//mDxDevice.RenderState.BlendOperation = BlendOperation.Min;
					mDxDevice.RenderState.AlphaBlendOperation = BlendOperation.Min;
					mDxDevice.RenderState.AlphaDestinationBlend = Blend.DestinationColor;
					mDxDevice.RenderState.AlphaFunction = Compare.Always;
					mDxDevice.RenderState.AlphaSourceBlend = Blend.SourceColor;
					mDxDevice.RenderState.BlendFactor = Color.White;
				}
				if (value == 1)
				{
					//alpha blending looks good with transparency too.			
					mDxDevice.RenderState.DestinationBlend = Blend.DestinationColor;
					//mDxDevice.RenderState.DestinationBlend = Blend.BlendFactor;
					//mDxDevice.RenderState.BlendFactor = Color.FromArgb(255, 122, 122, 122);
					mDxDevice.RenderState.SourceBlend = Blend.SourceColor;
					mDxDevice.RenderState.BlendOperation = BlendOperation.Add;
					//mDxDevice.RenderState.AlphaBlendEnable = true;
				}
				else if (value == 2)
				{
					//alpha blending looks good with transparency too.			
					mDxDevice.RenderState.DestinationBlend = Blend.DestinationColor;
					//mDxDevice.RenderState.DestinationBlend = Blend.BlendFactor;
					//mDxDevice.RenderState.BlendFactor = Color.FromArgb(255, 122, 122, 122);
					mDxDevice.RenderState.SourceBlend = Blend.SourceColor;
					mDxDevice.RenderState.BlendOperation = BlendOperation.Add;
					//mDxDevice.RenderState.AlphaBlendEnable = true;
				}
				else if (value == 3)
				{
				 	//alpha blending looks good with transparency too.			
					//mDxDevice.RenderState.DestinationBlend = Blend.
					mDxDevice.RenderState.DestinationBlend = Blend.BlendFactor;
					mDxDevice.RenderState.BlendFactor = Color.FromArgb(255, 122, 122, 122);
					mDxDevice.RenderState.SourceBlend = Blend.SourceColor;
					mDxDevice.RenderState.BlendOperation = BlendOperation.Add;
					//mDxDevice.RenderState.AlphaBlendEnable = true;
				}
				else if (value == 4)
				{
					//alpha blending looks good with transparency too.			
					//mDxDevice.RenderState.DestinationBlend = Blend.SourceColor;// Blend.SourceColor;
					mDxDevice.RenderState.DestinationBlend = Blend.InvSourceColor;
					//mDxDevice.RenderState.BlendFactor = Color.FromArgb(255, 122, 122, 122);
					mDxDevice.RenderState.SourceBlend = Blend.InvDestinationColor;
					mDxDevice.RenderState.BlendOperation = BlendOperation.Add;
					//mDxDevice.RenderState.AlphaBlendEnable = true;
				}
				if (value == 5)
				{
					//alpha blending looks good with transparency too.			
					//mDxDevice.RenderState.DestinationBlend = Blend.DestinationColor;
					mDxDevice.RenderState.DestinationBlend = Blend.BlendFactor;
					mDxDevice.RenderState.BlendFactor = Color.FromArgb(122, 122, 122, 122);
					mDxDevice.RenderState.SourceBlend = Blend.SourceColor;
					mDxDevice.RenderState.BlendOperation = BlendOperation.Add;
					//mDxDevice.RenderState.AlphaBlendEnable = true;
				}

			}
		}
		private bool mStencilEnable;
		[PGBrowsable]
		public bool StencilEnable
		{
			get { return mDxDevice.RenderState.StencilEnable; }
			set
			{
                mStencilEnable = value;
				if (value == true)
				{
					mDxDevice.RenderState.StencilEnable = true;
					//mDxDevice.RenderState.StencilWriteMask = 256*256-1 ; //works but i dont want to leave it in because i didnt see a change.
					mDxDevice.RenderState.StencilFunction = Compare.Greater;
				}
				else
					mDxDevice.RenderState.StencilEnable = false;
			}
		}
		//mDxDevice.RenderState.StencilEnable = true;
		protected void ResetDefaultMaterial()
		{
			mMaterial = new Material();
            mMaterial.Specular = Color.FromArgb(0, 255, 255, 255);
			mMaterial.Diffuse = Color.FromArgb(0, 255 ,255, 255);
			mMaterial.Ambient = Color.FromArgb(255, 255, 255, 255);   //change for color
            //mMaterial.Specular = Color.FromArgb(255, Color.ForestGreen);
			mDxDevice.Material = mMaterial;
		}

		//setup the lights and lighting to be used 
		protected void InitializeOrResetLights()
		{
			Light L0 = mDxDevice.Lights[0];

			L0.Ambient = Color.White;
			L0.Diffuse = Color.White; //black for none
			L0.Specular = Color.White;
			L0.Position = new Vector3(500,  500, 500); //tran of light
			Vector3 direction = new Vector3(0, 0, -5);
			direction.Normalize();
			L0.Direction = direction;
			L0.Type = LightType.Point;
			L0.Attenuation0 = .1f;
			L0.Attenuation1 = 0f;
            L0.Attenuation2 = 0f;
            L0.Falloff = 1f;
            L0.InnerConeAngle = 0;
            L0.OuterConeAngle = (float)Math.PI / 4;
			L0.Range = 10000;
			L0.Enabled = false; //true
            L0.Update();

			Light L1 = mDxDevice.Lights[1];
			L1.Ambient = Color.White;
			L1.Specular = Color.White;
			L1.Diffuse = Color.White; //black for none
			L1.Position = new Vector3(500, -500, 500); //tran of light
			Vector3 direction1 = new Vector3(0, 0, -5);
			direction1.Normalize();
			L1.Direction = direction1;
			L1.Type = LightType.Directional;
			L1.Attenuation0 = .1f;
			L1.Attenuation1 = .1f;
			L1.Attenuation2 = 0f;//L0.Attenuation1;
			//L0.Attenuation2;
			L1.Falloff = 1f;
			L1.Range = 10000;
			L1.InnerConeAngle = 0;
			L1.OuterConeAngle = (float)Math.PI / 4;
			L1.Enabled =  true;
			L1.Update();

			Light L2 = mDxDevice.Lights[2];
			L2.Ambient = Color.White;
			L2.Diffuse = Color.White; // black for none
			L2.Specular = Color.White;
			L2.Type = LightType.Spot;
			L2.Position = new Vector3(-500, 500, 500); //tran of light
            Vector3 l2Direction = new Vector3(0, 0, -5);
            l2Direction.Normalize();
            L2.Direction = l2Direction;
			L2.Attenuation0 = .10f;
			L2.Attenuation1 = .10f;
			L2.Attenuation2 = 0.0f;
			L2.Falloff = 1f;
			L2.InnerConeAngle = 0;
			L2.OuterConeAngle = (float)Math.PI / 4;
			L2.Range = 10000;
			L2.Enabled = false;
            L2.Update();

			Light L3 = mDxDevice.Lights[3];
			L3.Ambient = Color.White;
			L3.Diffuse = Color.White;
			L3.Specular = Color.White;
			L3.Position = new Vector3(-500, -500, 500);
            Vector3 l3Direction = new Vector3(0, 0, -5);
            l3Direction.Normalize();
			L3.Type = LightType.Point;
            L3.Direction = l3Direction;
			L3.Attenuation0 = .1f;
			L3.Attenuation1 = .1f;
			L3.Falloff = 1f;
			L3.Range = 10000;
			L3.Enabled = false;
            L3.Update();
		}

		private float projectionMaxZ = 1000000;
		public float ProjectionMaxZ
		{
			get { return projectionMaxZ; }
			//set { projectionMaxZ = value; }
		}
		private  float projectionMinZ = 1;
		public float ProjectionMinZ
		{
			get { return projectionMinZ; }
			//set { projectionMinZ = value; }
		}

		private float viewportMinZ = 0;
		public float ViewportMinZ
		{
			get { return viewportMinZ; }
			//set { viewportMinZ = value; }
		}
		private float viewPortMaxZ = 1;
		public float ViewPortMaxZ
		{
			get { return viewPortMaxZ; }
			//set { viewPortMaxZ = value; }
		}
		public void SetViewport()
		{
			if (mDxDevice != null)
			{
                //setup viewport
                Viewport viewPort = new Viewport();
				viewPort.X = 0; viewPort.Y = 0;
				viewPort.Width = mFrm.ClientSize.Width; //was the form width but we dipsay in a control now..
				viewPort.Height = mFrm.ClientSize.Height;
				viewPort.MinZ = viewportMinZ ; viewPort.MaxZ = viewPortMaxZ; //http://msdn.microsoft.com/en-us/library/microsoft.windowsmobile.directx.direct3d.viewport.aspx

				mDxDevice.Viewport = viewPort;
			}
		}
		[PGBrowsable]
		public Viewport ViewPort	  //make it an object so we can return null if necessary
		{
			get
			{
				//if (mDxDevice != null)
					return mDxDevice.Viewport;
				//else
				//    return null;
			}
		}
		public Matrix Projection
		{
			get
			{
				return DxDevice.Transform.Projection;
			}
		}
		[PGBrowsable]
		public Transforms Transform
		{
			get
			{
				return DxDevice.Transform;
			}
		}
		public Matrix View
		{
			get
			{
				return DxDevice.Transform.View;
			}
		}
		public Matrix World
		{

			get
			{ return DxDevice.Transform.World;	 }
		}
		//void SetupCamera()
		//{
		//    //cameraMatrix = Matrix.LookAtLH(	RelativeCameraPosition,	CameraTarget, cameraUpVector);
		//    mDxDevice.Transform.View = cameraMatrix;//
		//    //mDxDevice.Transform.World = 
		//}

		public void SetupTransformProjection()
		{
			/*' For the projection matrix,set up a perspective transform (which
			' transforms geometry from 3-D view space to 2-D viewport space, with
			' a perspective divide that makes objects smaller in the distance). To build
			' a perspective transform, you need the field of view (1/4 PI is common),
			' the aspect ratio, and the near and far clipping planes (which define at
			' the distances at which geometry should be no longer be rendered).
			*/

			//mDxDevice.Transform.Projection = Matrix.OrthoRH(width, height, zNearPlane, zFarPlane);

			//Orthographic projection 
            float width = mFrm.ClientSize.Width;
            float height = mFrm.ClientSize.Height;
			float FOVY = (float)Math.PI / 4; //45 degrees
			
			float aspectRatio = 1;
			if (height != 0)
			 	aspectRatio = width / height;

			mDxDevice.Transform.Projection = Matrix.PerspectiveFovLH(FOVY, aspectRatio, projectionMinZ, projectionMaxZ);

            //mDxDevice.Transform.Projection = Matrix.PerspectiveFovLH( FOV_Y, aspectRatio, znearPlane, zFarPlane ); //if ratio not equal 1
            //float minHeight = (width < height) ? width : height;
            //float FOVY2 = (float)(Math.PI / 4);	  
			
			//float aspectRatio = 1;//(float)width/height
			//mDxDevice.Transform.Projection = Matrix.PerspectiveFovLH(FOVY, aspectRatio, znearPlane, zFarPlane); //if ratio not equal 1
			 

		}
		public Device DXDevice
		{
			get { return mDxDevice; }
		}
/// <summary>
/// Good old static void Main... first part of the program to be run, 
/// </summary>
static void Main() //do not modify, use Render
{
	MainProgram dxWin = new MainProgram();
	//dxWin.mFrm.Show();

	///Begin runing standard managed Windows loop.
	while (!ExitProgram) 
	{
		//try
		//{
		try
		{
			Application.DoEvents(); //end run standard managed windows loop
			if (!ExitProgram)
				dxWin.RenderScene(); //use this, but dont modify the order of the statments in this loop.
		}
		catch (OutOfMemoryException e)
		{
			OutputForm.PrimaryOutputForm.OutputThenGoAway("Out of memory Exception caught.", 10000);
		}
		//}
		//catch (Exception epsilon)
		//{
		//	//continue unchanged it will eventually finish garbage collecting
		//}
	}
	dxWin = null;
}
		
		private Color clearColor = Color.Black;

		[PGBrowsable]
		public Color ClearColor
		{
			get { return clearColor; }
			set { clearColor = value; }
		}

		/// <summary>
		/// //THIS IS AN IMPORTANT RENDER DISPLAY METHOD!
		/// </summary>
		public void RenderScene()
		{
			if (mDxDevice != null)
			{
				if (exitProgram) return;

				//mDxDevice.Clear(ClearFlags.ZBuffer, Color.White, 1f, 0);// 
				mDxDevice.Clear(ClearFlags.Target,ClearColor, 1f, 0);// 
				mDxDevice.BeginScene();
				if (exitProgram) return;
				mRendererManager.DoManagedRender();
	
				if (exitProgram) return;
				mDxDevice.EndScene();
				mDxDevice.Present();
			}
		}


	}  //END OF CLASS
}	//END OF NAMESPACE